package com.own.business.login.phone.controller;

import com.own.aop.login.LoginIgnore;
import com.own.business.login.core.util.LoginCommonUtil;
import com.own.business.login.phone.core.form.LoginPhoneForm;
import com.own.business.login.phone.core.form.PhoneCodeForm;
import com.own.business.login.phone.core.property.LoginPhoneProperty;
import com.own.business.login.phone.core.service.LoginPhoneService;
import com.own.business.system.account.common.em.AccountType;
import com.own.component.common.base.controller.BaseController;
import com.own.component.common.exception.BusinessException;
import com.own.component.common.login.util.LoginInfoUtil;
import com.own.component.common.model.R;
import com.own.component.common.model.ResultModel;
import com.own.component.common.util.IpUtil;
import com.own.component.log.operation.aop.LogOperationAop;
import com.own.component.sms.core.util.code.SmsCodeUtil;
import com.own.component.store.core.util.base.RsaKeyUtil;
import com.own.constant.ConstantApiPrefix;
import com.own.constant.ConstantBeanSuffix;
import com.own.constant.ConstantEnvironmentType;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * LoginPhoneController
 *
 * @author chenxueli
 * @date 2023-06-25 21:47:32
 */
@Slf4j
@Tag(name = "手机登录授权" + ConstantBeanSuffix.CONTROLLER)
@RestController
@RequestMapping(ConstantApiPrefix.BASE_API_V1_PREFIX + "phone/login")
public class LoginPhoneController extends BaseController {

    @Resource
    private LoginPhoneService loginPhoneService;

    @Resource
    private LoginPhoneProperty loginPhoneProperty;

    @Resource
    private LoginCommonUtil loginCommonUtil;

    @Resource
    private SmsCodeUtil smsCodeUtil;
    @Resource
    private LoginInfoUtil loginInfoUtil;

    @Resource
    private RsaKeyUtil rsaKeyUtil;

    //    @LoginApiAop(account = "#form.phone", type = "phone")
    @LoginIgnore
    @LogOperationAop
    @Operation(summary = "手机验证码登录")
    @PostMapping("/")
    public ResultModel<String> login(
            @RequestBody LoginPhoneForm form,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        form.check();
        // 获取密码
        var password = StringUtils.isBlank(form.getPassword()) ? null : rsaKeyUtil.decrypt(form.getKey(), form.getPassword(), false);
        var model = smsCodeUtil.verification(form.getPhone(), form.getKey(), form.getCode());
        if (!model.success()) {
            throw new BusinessException("验证码不正确");
        }
        var phone = model.phone();
        // 设置登录方式信息
        loginInfoUtil.type().set(AccountType.PHONE.type());
        loginInfoUtil.account().set(phone);
        loginInfoUtil.code().set(form.getCode());
        // 设置登录用户的ip地址
        form.setIp(IpUtil.getIpAddress(request));
        // 获取token
        var vo = loginCommonUtil.login(() -> loginPhoneService.login(model.phone(), password, form.getType()), request, response);
        // 返回信息
        return R.success(vo.getToken(), "登录成功");
    }

    @LoginIgnore
    @LogOperationAop
    @Operation(summary = "验证手机号")
    @PostMapping("/check/phone")
    public ResultModel<Boolean> checkPhone(
            @RequestBody LoginPhoneForm form
    ) {
        form.check();
        var model = smsCodeUtil.verification(form.getPhone(), form.getKey(), form.getCode());
        return R.success(model.success());
    }

    @LoginIgnore
    @LogOperationAop
    @Operation(summary = "获取手机验证码")
    @PostMapping("/code")
    public ResultModel<Boolean> getCode(
            @RequestBody PhoneCodeForm form
    ) {
        form.check();
        smsCodeUtil.build(form.getPhone(), form.getKey(), loginPhoneProperty, false);
        return R.success(true);
    }

    @LoginIgnore
    @LogOperationAop
    @Profile({ConstantEnvironmentType.DEV, ConstantEnvironmentType.LOCALHOST, ConstantEnvironmentType.TEST})
    @Operation(summary = "获取手机验证码（显示验证码）")
    @PostMapping("/code/show")
    public ResultModel<String> getCodeShow(
            @RequestBody PhoneCodeForm form
    ) {
        form.check();
        var model = smsCodeUtil.build(form.getPhone(), form.getKey(), loginPhoneProperty, true);
        return R.success(model.getCode());
    }

    @LoginIgnore
    @LogOperationAop
    @Profile({ConstantEnvironmentType.DEV, ConstantEnvironmentType.LOCALHOST, ConstantEnvironmentType.TEST})
    @Operation(summary = "获取缓存中的手机验证码")
    @GetMapping("/phone/code/{phone}")
    public ResultModel<String> code(
            @Parameter(description = "手机号") @PathVariable String phone
    ) {
        var code = smsCodeUtil.getCode(phone);
        return R.success(code);
    }

}
